package com.linkstec.util;

import java.io.IOException;
import java.util.HashMap;
import java.util.concurrent.CountDownLatch;

import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.concurrent.FutureCallback;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.nio.client.CloseableHttpAsyncClient;
import org.apache.http.impl.nio.client.HttpAsyncClients;
import org.apache.http.impl.nio.conn.PoolingNHttpClientConnectionManager;
import org.apache.http.impl.nio.reactor.DefaultConnectingIOReactor;
import org.apache.http.impl.nio.reactor.IOReactorConfig;
import org.apache.http.nio.reactor.ConnectingIOReactor;
import org.apache.http.nio.reactor.IOReactorException;
import org.apache.http.util.EntityUtils;

import com.alibaba.fastjson.JSON;

import lombok.extern.slf4j.Slf4j;

@Slf4j
public class HttpAsyncClientUtil {

    static CloseableHttpAsyncClient client = null;
    static StringEntity entity = null;

    public static void post(String url, HashMap<String, Object> map, CountDownLatch countDownLatch) {

        HttpPost httpPost = getHttpPost(url);
        StringEntity entity = getEntity(map);

        httpPost.setEntity(entity);
        // 异步请求
        client.execute(httpPost, new Back(countDownLatch));

    }

    public static void get(String url, CountDownLatch countDownLatch) {

        HttpGet httpGet = new HttpGet(url);
        // 异步请求
        client.execute(httpGet, new Back(countDownLatch));

    }

    public static HttpPost getHttpPost(String urlPost) {

        HttpPost httpPost = new HttpPost(urlPost);
        httpPost.setHeader("Content-Type", "application/json;encoding=utf-8");

        return httpPost;
    }

    public static CloseableHttpAsyncClient getClient() {
        // 设置代理IP、端口、协议（请分别替换）
//		HttpHost proxy = new HttpHost("172.16.0.1", 3128, "http");

        RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(50000).setSocketTimeout(50000)
                .setConnectionRequestTimeout(1000)
//				.setProxy(proxy)
                .build();

        // 配置io线程
        IOReactorConfig ioReactorConfig = IOReactorConfig.custom()
                .setIoThreadCount(Runtime.getRuntime().availableProcessors()).setSoKeepAlive(true).build();
        // 设置连接池大小
        ConnectingIOReactor ioReactor = null;
        try {
            ioReactor = new DefaultConnectingIOReactor(ioReactorConfig);
        } catch (IOReactorException e) {
            e.printStackTrace();
        }
        PoolingNHttpClientConnectionManager connManager = new PoolingNHttpClientConnectionManager(ioReactor);
        connManager.setMaxTotal(100);
        connManager.setDefaultMaxPerRoute(100);

        client = HttpAsyncClients.custom().setConnectionManager(connManager).setDefaultRequestConfig(requestConfig)
                .build();

        return client;
    }

    public static StringEntity getEntity(HashMap<String, Object> map) {

        try {

            String a = new String(JSON.toJSONString(map));
            log.info(a);
            // entity = new StringEntity(a);//中文乱码
            entity = new StringEntity(a, "UTF-8");
            entity.setContentType("application/json; charset=utf-8");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return entity;
    }

    public static void startHttpAsyncClient() {
        client.start();
    }

    public static void closeHttpAsyncClient() {
        try {
            client.close();
        } catch (IOException e) {
            log.error("", e);
        }
    }

    static class Back implements FutureCallback<HttpResponse> {

        private long start = System.currentTimeMillis();
        private CountDownLatch countDownLatch;

        Back(CountDownLatch countDownLatch) {
            this.countDownLatch = countDownLatch;
        }

        @Override
        public void completed(HttpResponse httpResponse) {
            try {
                log.info("cost is:" + (System.currentTimeMillis() - start) + ":"
                        + EntityUtils.toString(httpResponse.getEntity()));
                int statusCode = httpResponse.getStatusLine().getStatusCode();
                if (HttpStatus.SC_OK == statusCode) {
                    log.info("成功");
                } else {
                    log.info("失败");
                }

                countDownLatch.countDown();
            } catch (Exception e) {
            }
        }

        @Override
        public void failed(Exception e) {
            countDownLatch.countDown();
            log.error("错误 cost is:" + (System.currentTimeMillis() - start) + ":" + e);
        }

        @Override
        public void cancelled() {
            countDownLatch.countDown();

        }
    }

}